
/*
 *
 * Most of this source has been derived from the Linux USB
 * project:
 * (C) Copyright Linus Torvalds 1999
 * (C) Copyright Johannes Erdfelt 1999-2001
 * (C) Copyright Andreas Gal 1999
 * (C) Copyright Gregory P. Smith 1999
 * (C) Copyright Deti Fliegl 1999 (new USB architecture)
 * (C) Copyright Randy Dunlap 2000
 * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
 * (C) Copyright Yggdrasil Computing, Inc. 2000
 *     (usb_device_id matching changes by Adam J. Richter)
 *
 * Adapted for U-Boot:
 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 */
/*
 * How it works:
 *
 * Since this is a bootloader, the devices will not be automatic
 * (re)configured on hotplug, but after a restart of the USB the
 * device should work.
 *
 * For each transfer (except "Interrupt") we wait for completion.
 */
//#include <common.h>
//#include <command.h>
//#include <asm/processor.h>
//#include <linux/ctype.h>
#include "usb.h"
#include "base.h"
#include "s3c2410.h"

//#undef USB_DEBUG
#define  USB_DEBUG
#ifdef	USB_DEBUG
#define	USB_PRINTF s_UartPrint
#else
#define USB_PRINTF()
#endif
#define USB_BUFSIZ	512

/* Command Block Wrapper */
typedef struct
{
    U32     dCBWSignature;
    #define CBWSIGNATURE    0x43425355
    U32     dCBWTag;
    U32     dCBWDataTransferLength;
    U8      bCBWFlags;
    #define CBWFLAGS_OUT    0x00
    #define CBWFLAGS_IN 0x80
    U8      bCBWLUN;
    U8      bCBWCBLength;
    #define CBWCDBLENGTH    16
    U8      CBWCDB[CBWCDBLENGTH];
} umass_bbb_cbw_t;

typedef struct 
{
    U32		dCSWSignature;
    #define CSWSIGNATURE	0x53425355
    U32		dCSWTag;
    U32		dCSWDataResidue;
    U8		bCSWStatus;
    #define CSWSTATUS_GOOD	0x0
    #define CSWSTATUS_FAILED 0x1
    #define CSWSTATUS_PHASE	0x2
} umass_bbb_csw_t;

static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
static int running;
static int asynch_allowed;
static struct devrequest setup_packet;
static U32 cbwtag = 0;
static U32 ed_in_toogle = 0;
static U32 ed_out_toogle = 0;
//extern void hc_interrupt_irq (void);
/**********************************************************************
 * some forward declerations...
 */
void usb_scan_devices(void);
void init_root_hub(void);
int   usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
void gm_init_root_hub(void);

void udelay (unsigned long usec)
{
    unsigned long j,i;
    //for(i=0;i<50;i++);   
    j=usec/1000;
    for(i=0;i<j;i++)
    {
        rINTMSK |= (1<<13);
        rTCON &= ~(0x0f<<16);  //stop timer3
        rSRCPND = (1<<13);		   
        rTCNTB3 = 2028;         //1ms=2028
        rTCMPB3=0;
        rTCON &= ~(0x0f<<16);   //STOP TIMER 3
        rTCON |= (0x02<<16); // AUTOLOAD=0 update=1
        rTCON &= ~(1<<17);   //CLEAR MANUAL UPDATE BIT
        rTCON |= (1<<16);    //START
        while((rSRCPND & (1<<13))==0);
        rSRCPND = (1<<13);	
    }
}


/***********************************************************************
 * wait_ms
 */
void __inline wait_ms(unsigned long ms)
{
    while(ms-->0)
    udelay(1000);
}


void TestWaitMs(void)
{
    int i,j;
    s_UartPrint("Test Wait Ms... Any Key to Start...\n");
    s_getkey();
    j=0;
    for(i=0;i<120;i++)
    {
        s_UartPrint("j=%d sec\n",j);
        wait_ms(1000);  
        j++;
    }
}

int gm_usb_init(void)
{
    int result;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* init low_level USB */
	result = gm_usb_lowlevel_init();
    if(result==0) {
		gm_init_root_hub();
        return 0;
    }else {
        s_UartPrint("Error, couldn't init Lowlevel part\n");
        return -1;
    }
}

/***************************************************************************
 * Init USB Device
 */
int usb_init(void)
{
    int result;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
#if 0
    running=0;
    dev_index=0;
    asynch_allowed=1;
#endif
    //usb_hub_reset();
    /* init low_level USB */
	result = gm_usb_lowlevel_init();
    //result = usb_lowlevel_init();
    /* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */
    if(result==0) 
    {
        
        //running=1;

		gm_init_root_hub();
		//init_root_hub();
        //usb_scan_devices();
        return 0;
    }
    else 
    {
        s_UartPrint("Error, couldn't init Lowlevel part\n");
        return -1;
    }
}


/******************************************************************************
 * Stop USB this stops the LowLevel Part and deregisters USB devices.
 */
int usb_stop(void)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    asynch_allowed=1;
	
    usb_hub_reset();
    return usb_lowlevel_stop();
}


/*
 * disables the asynch behaviour of the control message. This is used for data
 * transfers that uses the exclusiv access to the control and bulk messages.
 */
void usb_disable_asynch(int disable)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    asynch_allowed=!disable;
}


/*-------------------------------------------------------------------
 * Message wrappers.
 *
 */
/*
 * submits an Interrupt Message
 */
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
void *buffer,int transfer_len, int interval)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return submit_int_msg(dev,pipe,buffer,transfer_len,interval);
}

void gm_usb_control_msg(void *data, unsigned short size)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
	/* 数据方向, 设备到主机 */
    setup_packet.requesttype = 0x80;
	/* 请求类型: 获取描述符 */
    setup_packet.request = 0x6;
	/* 0x100>>8 : 描述符类型,为DEVICE, 值为1..
	 * 0x100&0xFF: 描述符索引,0.*/
    setup_packet.value = 0x100;
    setup_packet.index = 0;
	/* 所请求的描述符长度. */
    setup_packet.length = 0x8;

	gm_submit_common_msg(data, size, &setup_packet);
}


/*
 * submits a control message and waits for comletion (at least timeout * 1ms)
 * If timeout is 0, we don't wait for completion (used as example to set and
 * clear keyboards LEDs). For data transfers, (storage transfers) we don't
 * allow control messages with 0 timeout, by previousely resetting the flag
 * asynch_allowed (usb_disable_asynch(1)).
 * returns the transfered length if OK or -1 if error. The transfered length
 * and the current status are stored in the dev->act_len and dev->status.
 */
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
					unsigned char request, unsigned char requesttype,
					unsigned short value, unsigned short index,
					void *data, unsigned short size, int timeout)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */
	    return -1;
    /* set setup command */
    setup_packet.requesttype = 0x80;//requesttype;
    setup_packet.request = 0x6;//request;
    setup_packet.value = 0x100;//swap_16(value);
    setup_packet.index = 0;//swap_16(index);
    setup_packet.length = 0x12;//swap_16(size);

    USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X\nvalue 0x%X index 0x%X length 0x%X pipe 0x%X \n",
    									request,requesttype,value,index,size,pipe);

    dev->status=USB_ST_NOT_PROC; /*not yet processed */

	gm_submit_common_msg(data, size, &setup_packet);
    //submit_control_msg(dev,pipe,data,size,&setup_packet);

    if(timeout==0) 
    {
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
        return (int)size;
    }

    while(timeout--) 
    {
        if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
	        break;

        wait_ms(1);
    }

    if(dev->status==0){
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	    return (int)size; //dev->act_len;
	}
    else 
    {
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
        return -1;
    }
}


/*-------------------------------------------------------------------
 * submits bulk message, and waits for completion. returns 0 if Ok or
 * -1 if Error.
 * synchronous behavior
 */
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if (len < 0)
    return -1;
    dev->status=USB_ST_NOT_PROC; /*not yet processed */
    submit_bulk_msg(dev,pipe,data,len);
    while(timeout--) 
    {
        if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
        break;
        wait_ms(1);
    }
    *actual_length=dev->act_len;
    if(dev->status==0)
    return 0;
    else
    return -1;
}


/*-------------------------------------------------------------------
 * Max Packet stuff
 */
/*
 * returns the max packet size, depending on the pipe direction and
 * the configurations values
 */
int usb_maxpacket(struct usb_device *dev,unsigned long pipe)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */
    return(dev->epmaxpacketout[((pipe>>15) & 0xf)]);
    else
    return(dev->epmaxpacketin[((pipe>>15) & 0xf)]);
}

int roothub_set_maxpacket(struct usb_device *dev)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    {
        {
            {
                {
                    /* IN Endpoint */
                    {
                        dev->epmaxpacketin[1] = 2;//ep->wMaxPacketSize;
                    }
                } 
                /* if out */
            } 
            /* if control */
        } 
        /* for each endpoint */
    }
    return 0;
}

/*
 * set the max packed value of all endpoints in the given configuration
 */
int usb_set_maxpacket(struct usb_device *dev)
{
    int i,ii,b;
    struct usb_endpoint_descriptor *ep;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	s_UartPrint("%s,%d: numinterfaces %d.\n", __func__, __LINE__, dev->config.bNumInterfaces);
    for(i=0; i<dev->config.bNumInterfaces;i++) 
    {
        for(ii=0; ii<dev->config.if_desc[i].bNumEndpoints; ii++) 
        {
            ep=&dev->config.if_desc[i].ep_desc[ii];
            b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
            if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) 
            {
                /* Control => bidirectional */
                dev->epmaxpacketout[b] = ep->wMaxPacketSize;
                dev->epmaxpacketin [b] = ep->wMaxPacketSize;
                USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]);
            }
            else 
            {
                if ((ep->bEndpointAddress & 0x80)==0) 
                {
                    /* OUT Endpoint */
                    if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) 
                    {
                        dev->epmaxpacketout[b] = ep->wMaxPacketSize;
                        USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]);
                    }
                }
                else  
                {
                    /* IN Endpoint */
                    if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) 
                    {
                        dev->epmaxpacketin[b] = ep->wMaxPacketSize;
                        USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]);
                    }
                } 
                /* if out */
            } 
            /* if control */
        } 
        /* for each endpoint */
    }
    return 0;
}


/*******************************************************************************
 * Parse the config, located in buffer, and fills the dev->config structure.
 * Note that all little/big endian swapping are done automatically.
 */
int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
{
    struct usb_descriptor_header *head;
    int index,ifno,epno;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    ifno=-1;
    epno=-1;
    dev->configno=cfgno;
    head =(struct usb_descriptor_header *)&buffer[0];
    if(head->bDescriptorType!=USB_DT_CONFIG) 
    {
        s_UartPrint(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
        return -1;
    }
    memcpy(&dev->config,buffer,buffer[0]);
    dev->config.wTotalLength=swap_16(dev->config.wTotalLength);
    dev->config.no_of_if=0;
    index=dev->config.bLength;
    /* Ok the first entry must be a configuration entry, now process the others */
    head=(struct usb_descriptor_header *)&buffer[index];
    while(index+1 < dev->config.wTotalLength) 
    {
        switch(head->bDescriptorType) 
        {
        case USB_DT_INTERFACE:
            ifno=dev->config.no_of_if;
            dev->config.no_of_if++; /* found an interface desc, increase numbers */
            memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */
            dev->config.if_desc[ifno].no_of_ep=0;
            break;
        case USB_DT_ENDPOINT:
            epno=dev->config.if_desc[ifno].no_of_ep;
            dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
            memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]);
            dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize
            =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
            USB_PRINTF("if %d, ep %d\n",ifno,epno);
            break;
        default:
            if(head->bLength==0)
            return 1;
            USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType);
            {
                int i;
                unsigned char *ch;
                ch=(unsigned char *)head;
                for(i=0;i<head->bLength; i++)
                USB_PRINTF("%02X ",*ch++);
                USB_PRINTF("\n\n\n");
            }
            break;
        }
        index+=head->bLength;
        head=(struct usb_descriptor_header *)&buffer[index];
    }
    return 1;
}


/***********************************************************************
 * Clears an endpoint
 * endp: endpoint number in bits 0-3;
 * direction flag in bit 7 (1 = IN, 0 = OUT)
 */
int usb_clear_halt(struct usb_device *dev, int pipe)
{
    int result;
    int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
    /* don't clear if failed */
    if (result < 0)
    return result;
    /*
    	 * NOTE: we do not get status and verify reset was successful
    	 * as some devices are reported to lock up upon this check..
    	 */
    usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
    /* toggle is reset on clear */
    usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
    return 0;
}


/**********************************************************************
 * get_descriptor type
 */
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{
    int res = 0;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	gm_usb_control_msg(buf, size);
#if 0
    res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    						USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
						    (type << 8) + index, 0,
						    buf, size, USB_CNTL_TIMEOUT);
#endif
    return res;
}


/**********************************************************************
 * gets configuration cfgno and store it in the buffer
 */
int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno)
{
    int result;
    unsigned int tmp;
    struct usb_config_descriptor *config;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    config=(struct usb_config_descriptor *)&buffer[0];
    result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
    if (result < 8) 
    {
        if (result < 0)
        s_UartPrint("unable to get descriptor, error %lX\n",dev->status);
        else
        s_UartPrint("config descriptor too short (expected %i, got %i)\n",8,result);
        return -1;
    }
    tmp=swap_16(config->wTotalLength);
    if (tmp > USB_BUFSIZ) 
    {
        USB_PRINTF("usb_get_configuration_no: failed to get descriptor - too long: %d\n",
        tmp);
        return -1;
    }
    result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp);
    USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp);
    return result;
}


/********************************************************************
 * set address of a device to the value in dev->devnum.
 * This can only be done by addressing the device via the default address (0)
 */
int usb_set_address(struct usb_device *dev)
{
    int res;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    USB_PRINTF("set address %d\n",dev->devnum);
    res=usb_control_msg(dev, usb_snddefctrl(dev),
					USB_REQ_SET_ADDRESS, 0,
					(dev->devnum),0,
					NULL,0, USB_CNTL_TIMEOUT);
    return res;
}


/********************************************************************
 * set interface number to interface
 */
int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
    struct usb_interface_descriptor *if_face = NULL;
    int ret, i;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    for (i = 0; i < dev->config.bNumInterfaces; i++) 
    {
        if (dev->config.if_desc[i].bInterfaceNumber == interface) 
        {
            if_face = &dev->config.if_desc[i];
            break;
        }
    }
    if (!if_face) 
    {
        s_UartPrint("selecting invalid interface %d", interface);
        return -1;
    }
    if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
    interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0)
    return ret;
    return 0;
}


/********************************************************************
 * set configuration number to configuration
 */
int usb_set_configuration(struct usb_device *dev, int configuration)
{
    int res;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    USB_PRINTF("set configuration %d\n",configuration);
    /* set setup command */
    res=usb_control_msg(dev, usb_sndctrlpipe(dev,0),
						USB_REQ_SET_CONFIGURATION, 0,
						configuration,0,
						NULL,0, USB_CNTL_TIMEOUT);
    if(res==0) {
        dev->toggle[0] = 0;
        dev->toggle[1] = 0;
        return 0;
    }else
    	return -1;
}

/********************************************************************
 * set protocol to protocol
 */
int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
    protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
}


/********************************************************************
 * set idle
 */
int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
    (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
}


/********************************************************************
 * get report
 */
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
    (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
}


/********************************************************************
 * get class descriptor
 */
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
unsigned char type, unsigned char id, void *buf, int size)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
    (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
}


/********************************************************************
 * get string index in buffer
 */
int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
{
    int i;
    int result;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    for (i = 0; i < 3; ++i) 
    {
        /* some devices are flaky */
        result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
        (USB_DT_STRING << 8) + index, langid, buf, size,
        USB_CNTL_TIMEOUT);
        if (result > 0)
        break;
    }
    return result;
}


static void usb_try_string_workarounds(unsigned char *buf, int *length)
{
    int newlength, oldlength = *length;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
    if (!isprint(buf[newlength]) || buf[newlength + 1])
    break;
    if (newlength > 2) 
    {
        buf[0] = newlength;
        *length = newlength;
    }
}


static int usb_string_sub(struct usb_device *dev, unsigned int langid,
unsigned int index, unsigned char *buf)
{
    int rc;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    /* Try to read the string descriptor by asking for the maximum
    	 * possible number of bytes */
    rc = usb_get_string(dev, langid, index, buf, 255);
    /* If that failed try to read the descriptor length, then
    	 * ask for just that many bytes */
    if (rc < 2) 
    {
        rc = usb_get_string(dev, langid, index, buf, 2);
        if (rc == 2)
        rc = usb_get_string(dev, langid, index, buf, buf[0]);
    }
    if (rc >= 2) 
    {
        if (!buf[0] && !buf[1])
        usb_try_string_workarounds(buf, &rc);
        /* There might be extra junk at the end of the descriptor */
        if (buf[0] < rc)
        rc = buf[0];
        rc = rc - (rc & 1); /* force a multiple of two */
    }
    if (rc < 2)
    rc = -1;
    return rc;
}


/********************************************************************
 * usb_string:
 * Get string index and translate it to ascii.
 * returns string length (> 0) or error (< 0)
 */
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
    unsigned char mybuf[USB_BUFSIZ];
    unsigned char *tbuf;
    int err;
    unsigned int u, idx;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if (size <= 0 || !buf || !index)
    return -1;
    buf[0] = 0;
    tbuf=&mybuf[0];
    /* get langid for strings if it's not yet known */
    if (!dev->have_langid) 
    {
        err = usb_string_sub(dev, 0, 0, tbuf);
        if (err < 0) 
        {
            USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status);
            return -1;
        } 
        else if (tbuf[0] < 4) 
        {
            USB_PRINTF("string descriptor 0 too short\n");
            return -1;
        } 
        else 
        {
            dev->have_langid = -1;
            dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
            /* always use the first langid listed */
            USB_PRINTF("USB device number %d default language ID 0x%x\n",
            dev->devnum, dev->string_langid);
        }
    }
    err = usb_string_sub(dev, dev->string_langid, index, tbuf);
    if (err < 0)
    return err;
    size--;		/* leave room for trailing NULL char in output buffer */
    for (idx = 0, u = 2; u < err; u += 2) 
    {
        if (idx >= size)
        break;
        if (tbuf[u+1])			/* high byte */
        buf[idx++] = '?';  /* non-ASCII character */
        else
        buf[idx++] = tbuf[u];
    }
    buf[idx] = 0;
    err = idx;
    return err;
}


/********************************************************************
 * USB device handling:
 * the USB device are static allocated [USB_MAX_DEVICE].
 */
/* returns a pointer to the device with the index [index].
 * if the device is not assigned (dev->devnum==-1) returns NULL
 */
struct usb_device * usb_get_dev_index(int index)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if(usb_dev[index].devnum==-1)
    return NULL;
    else
    return &usb_dev[index];
}


/* returns a pointer of a new device structure or NULL, if
 * no device struct is available
 */
struct usb_device * usb_alloc_new_device(void)
{
    int i;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    USB_PRINTF("New Device %d\n",dev_index);
    if(dev_index==USB_MAX_DEVICE) 
    {
        s_UartPrint("ERROR, too many USB Devices, max=%d\n",USB_MAX_DEVICE);
        return NULL;
    }
    usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */
    usb_dev[dev_index].maxchild=0;

    for(i=0;i<USB_MAXCHILDREN;i++)
    	usb_dev[dev_index].children[i]=NULL;

    usb_dev[dev_index].parent=NULL;
    dev_index++;
    return &usb_dev[dev_index-1];
}

int gm_usb_new_root_hub(void)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	set_root_hub_configration();
	gm_usb_hub_configure();

	return 0;
}

int usb_new_root_hub(struct usb_device *dev)
{
    int addr, err;
    int tmp;
    unsigned char *tmpbuf;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
#if 0
    dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
    dev->maxpacketsize = 0;		/* Default to 8 byte max packet size */
    dev->epmaxpacketin [0] = 8;
    dev->epmaxpacketout[0] = 8;
    /* We still haven't set the Address yet */
    addr = dev->devnum;
    dev->devnum = 0;
        /* and this is the old and known way of initializing devices */
    //s_UartPrint("NEW_step 1\n");
	memcpy(&dev->descriptor, GM_get_descriptor(0),8);
#endif
#if 0
    err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
    if (err < 8) 
    {
        s_UartPrint("\n      USB device not responding, giving up (status=%lX)\n",dev->status);
        return 1;
    }
#endif
#if 0
    //s_UartPrint("NEW_step 3 err=%d\n",err);
	dev->descriptor.bMaxPacketSize0 = 8;
    dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
    dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
    switch (dev->descriptor.bMaxPacketSize0) 
    {
        case 8: dev->maxpacketsize = 0; break;
        case 16: dev->maxpacketsize = 1; break;
        case 32: dev->maxpacketsize = 2; break;
        case 64: dev->maxpacketsize = 3; break;
    }
    dev->devnum = addr;
	set_root_hub_addr(addr);

    wait_ms(10);	/* Let the SET_ADDRESS settle */
	memcpy(&dev->descriptor, GM_get_descriptor(0),sizeof(dev->descriptor));
#endif
#if 0
    tmp = sizeof(dev->descriptor);
    err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
    if (err < tmp) 
    {
        if (err < 0)
        s_UartPrint("unable to get device descriptor (error=%d)\n",err);
        else
        s_UartPrint("USB device descriptor short read (expected %i, got %i)\n",tmp,err);
        s_UartPrint("NEW_step 8\n");
        return 1;
    }
#endif
#if 0
    /* correct le values */
    dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB);
    dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor);
    dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct);
    dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice);
    USB_PRINTF("bLength %x\n", dev->descriptor.bLength);
    USB_PRINTF("bDescriptorType      %x\n", dev->descriptor.bDescriptorType);
    USB_PRINTF("bcdUSB      %x\n", dev->descriptor.bcdUSB);
    USB_PRINTF("bDeviceClass     %x\n", dev->descriptor.bDeviceClass);
    USB_PRINTF("bDeviceSubClass     %x\n", dev->descriptor.bDeviceSubClass);
    USB_PRINTF("bDeviceProtocol      %x\n", dev->descriptor.bDeviceProtocol);
    USB_PRINTF("bMaxPacketSize0      %x\n", dev->descriptor.bMaxPacketSize0);
    USB_PRINTF("idVendor      %x\n", dev->descriptor.idVendor);
    USB_PRINTF("idProduct      %x\n", dev->descriptor.idProduct);
    USB_PRINTF("bcdDevice      %x\n", dev->descriptor.bcdDevice);
    USB_PRINTF("iManufacturer      %x\n", dev->descriptor.iManufacturer);
    USB_PRINTF("iProduct      %x\n", dev->descriptor.iProduct);
    USB_PRINTF("iSerialNumber      %x\n", dev->descriptor.iSerialNumber);
    USB_PRINTF("bNumConfigurations      %x\n", dev->descriptor.bNumConfigurations);
    /* only support for one config for now */
	tmpbuf = (unsigned char*)get_root_hub_configration();
    usb_parse_config(dev,&tmpbuf[0],0);
	roothub_set_maxpacket(dev);
#endif
    /* we set the default configuration here */
	set_root_hub_configration();
#if 0
    if (usb_set_configuration(dev, dev->config.bConfigurationValue)) 
    {
        s_UartPrint("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status);
        return -1;
    }
#endif
#if 0
    USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
    dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
    memset(dev->mf, 0, sizeof(dev->mf));
    memset(dev->prod, 0, sizeof(dev->prod));
    memset(dev->serial, 0, sizeof(dev->serial));
    if (dev->descriptor.iManufacturer)
	    usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf));
    if (dev->descriptor.iProduct)
    	usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod));
    if (dev->descriptor.iSerialNumber)
	    usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial));
    USB_PRINTF("Manufacturer %s\n", dev->mf);
    USB_PRINTF("Product      %s\n", dev->prod);
    USB_PRINTF("SerialNumber %s\n", dev->serial);
#endif
    /* now prode if the device is a hub */
    //usb_hub_probe(dev,0);
	gm_usb_hub_configure();
    return 0;
}

void print_data(unsigned char *data, int data_size)
{
	int i = 0;

	for(i=0; i<data_size; i++) {
		s_UartPrint("0x%x ", data[i]);
	}
}

void gm_set_HID_idle(void)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x21;
	/* 请求类型: get report */
    setup_packet.request = 0x0a;
	/* 输入报表, report id 为0 */
    setup_packet.value = 0x0;
	/* 接口号为0 */
    setup_packet.index = 0;
    setup_packet.length = 0;

	gm_ep_set(2,0,0,1,0,0,0x8);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 1, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

void gm_get_hid_report(void *data, int data_size)
{
	U32 td_info = 0;
	U32 request_len = 0x54;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x81;
	/* 请求类型: get descriptor */
    setup_packet.request = 0x6;
	/* report desc */
    setup_packet.value = 0x2200;
	/* 接口号为0 */
    setup_packet.index = 0;
    setup_packet.length = request_len;

	gm_ep_set(2,0,0,1,0,0,0x8);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 0, td_info, data, request_len);

	td_info = create_td_info(1, 1, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(2, 1, td_info, 0, 0);
#if 0
	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 0, td_info, data, 30);

	td_info = create_td_info(1, 2, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(2, 0, td_info, data, 30);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(3, 0, td_info, data, 30);

	td_info = create_td_info(1, 2, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(4, 0, td_info, data, 26);

	td_info = create_td_info(1, 1, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(5, 1, td_info, 0, 0);
#endif

	gm_start_td();

	gm_wait_hc_interrput();

	print_data(data, data_size);
}

void gm_get_IN_data(void *data, int data_size)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

	memset(data, 0, 10);
	/* 端点号为1, 不再是0 , 数据方向为接收.*/
	gm_interrupt_ep_set(2,1,2,1,0,0,0x8);

	/* 此处TD的toggle设置为从ED的c位获取. */
	td_info = create_td_info(1, 0x02, 0x00, 0x0, 0x0, 0xf);
	gm_set_td(0, 1, td_info, data, 8);

	gm_start_interrupt_td();
	
	gm_wait_hc_interrput();
	print_data(data, 9);
#if 0
	while(1){
		if(*(unsigned *)data != 0){
			print_data(data, 9);
		}
	}
#endif
}

void gm_set_configuration(int value)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x00;
	/* 请求类型: set config */
    setup_packet.request = 0x9;
    setup_packet.value = value;
    setup_packet.index = 0;
	/* 无 数据传输过程 */
    setup_packet.length = 0;

	gm_ep_set(2,0,0,0,0,0,0x8);

	//memset(mytd, 0, MAXTD);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

void gm_set_interface(int value)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x00;
    setup_packet.request = 11;
    setup_packet.value = value;
    setup_packet.index = 0;
	/* 无 数据传输过程 */
    setup_packet.length = 0;

	gm_ep_set(2,0,0,0,0,0,0x8);

	//memset(mytd, 0, MAXTD);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

/* 固定设置设备地址为2 */
void gm_set_device_address(void)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x00;
	/* 请求类型: set devie address */
    setup_packet.request = 0x5;
	/* set device address is 2 */
    setup_packet.value = 0x2;
    setup_packet.index = 0;
	/* 无 数据传输过程 */
    setup_packet.length = 0;

	gm_ep_set(0,0,0,0,0,0,0x8);

	//memset(mytd, 0, MAXTD);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
	//my_ep_link();

	//my_td_sumit(buffer, setup, transfer_len);
}

void gm_get_device_configuration(void *buffer, const int desc_size, int mps)
{
	U32 td_info = 0;
	//unsigned char buffer[30] = {0};

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x80;
	/* 请求类型: get descriptor */
    setup_packet.request = 0x6;
	/* 0x200 >>8: 2, 描述符类型, configuration; 0x200&0xFF: 00, 描述符索引. */
    setup_packet.value = 0x200;
    setup_packet.index = 0;

    setup_packet.length = desc_size;

	gm_ep_set(2,0,0,0,0,0,mps);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 0, td_info, (void *)buffer, desc_size);

	td_info = create_td_info(1, 1, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(2, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}


int gm_get_device_descriptor(void *buffer, const int desc_size, int mps, int de_addr)
{
	U32 td_info = 0;
	struct usb_device_descriptor *device_desc = NULL;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
    setup_packet.requesttype = 0x80;
	/* 请求类型: get descriptor */
    setup_packet.request = 0x6;
	/* 0x100 >>8: 1, 描述符类型, device; 0x100&0xFF: 00, 描述符索引. */
    setup_packet.value = 0x100;
    setup_packet.index = 0;

    setup_packet.length = desc_size;

	gm_ep_set(de_addr,0,0,0,0,0,mps);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 0, td_info, (void *)buffer, desc_size);

	td_info = create_td_info(1, 1, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(2, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();

	device_desc = (struct usb_device_descriptor *)buffer;

	return device_desc->bMaxPacketSize0;
#if 0
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

	gm_usb_control_msg(&dev->descriptor, sizeof(dev->descriptor));

    /* correct le values */
    dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB);
    dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor);
    dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct);
    dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice);
    USB_PRINTF("bLength %x\n", dev->descriptor.bLength);
    USB_PRINTF("bDescriptorType      %x\n", dev->descriptor.bDescriptorType);
    USB_PRINTF("bcdUSB      %x\n", dev->descriptor.bcdUSB);
    USB_PRINTF("bDeviceClass     %x\n", dev->descriptor.bDeviceClass);
    USB_PRINTF("bDeviceSubClass     %x\n", dev->descriptor.bDeviceSubClass);
    USB_PRINTF("bDeviceProtocol      %x\n", dev->descriptor.bDeviceProtocol);
    USB_PRINTF("bMaxPacketSize0      %x\n", dev->descriptor.bMaxPacketSize0);
    USB_PRINTF("idVendor      %x\n", dev->descriptor.idVendor);
    USB_PRINTF("idProduct      %x\n", dev->descriptor.idProduct);
    USB_PRINTF("bcdDevice      %x\n", dev->descriptor.bcdDevice);
    USB_PRINTF("iManufacturer      %x\n", dev->descriptor.iManufacturer);
    USB_PRINTF("iProduct      %x\n", dev->descriptor.iProduct);
    USB_PRINTF("iSerialNumber      %x\n", dev->descriptor.iSerialNumber);
    USB_PRINTF("bNumConfigurations      %x\n", dev->descriptor.bNumConfigurations);
#endif
}

/*
 * By the time we get here, the device has gotten a new device ID
 * and is in the default state. We need to identify the thing and
 * get the ball rolling..
 *
 * Returns 0 for success, != 0 for error.
 */
int usb_new_device(struct usb_device *dev)
{
    int addr, err;
    int tmp;
    unsigned char tmpbuf[USB_BUFSIZ];
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

#if 0
    dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
    dev->maxpacketsize = 0;		/* Default to 8 byte max packet size */
    dev->epmaxpacketin [0] = 8;
    dev->epmaxpacketout[0] = 8;
    /* We still haven't set the Address yet */
    addr = dev->devnum;
    dev->devnum = 0;
#endif
        /* and this is the old and known way of initializing devices */
    err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
#if 0
    if (err < 8) 
    {
        s_UartPrint("\n      USB device not responding, giving up (status=%lX)\n",dev->status);
        return 1;
    }
#endif
    dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
    dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;

    /* correct le values */
    dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB);
    dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor);
    dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct);
    dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice);
    USB_PRINTF("bLength %x\n", dev->descriptor.bLength);
    USB_PRINTF("bDescriptorType      %x\n", dev->descriptor.bDescriptorType);
    USB_PRINTF("bcdUSB      %x\n", dev->descriptor.bcdUSB);
    USB_PRINTF("bDeviceClass     %x\n", dev->descriptor.bDeviceClass);
    USB_PRINTF("bDeviceSubClass     %x\n", dev->descriptor.bDeviceSubClass);
    USB_PRINTF("bDeviceProtocol      %x\n", dev->descriptor.bDeviceProtocol);
    USB_PRINTF("bMaxPacketSize0      %x\n", dev->descriptor.bMaxPacketSize0);
    USB_PRINTF("idVendor      %x\n", dev->descriptor.idVendor);
    USB_PRINTF("idProduct      %x\n", dev->descriptor.idProduct);
    USB_PRINTF("bcdDevice      %x\n", dev->descriptor.bcdDevice);
    USB_PRINTF("iManufacturer      %x\n", dev->descriptor.iManufacturer);
    USB_PRINTF("iProduct      %x\n", dev->descriptor.iProduct);
    USB_PRINTF("iSerialNumber      %x\n", dev->descriptor.iSerialNumber);
    USB_PRINTF("bNumConfigurations      %x\n", dev->descriptor.bNumConfigurations);

	while(1);

	s_UartPrint("%s, max pack %d.\n", __func__, dev->descriptor.bMaxPacketSize0);
    switch (dev->descriptor.bMaxPacketSize0) 
    {
        case 8: dev->maxpacketsize = 0; break;
        case 16: dev->maxpacketsize = 1; break;
        case 32: dev->maxpacketsize = 2; break;
        case 64: dev->maxpacketsize = 3; break;
    }
    dev->devnum = addr;
    err = usb_set_address(dev); /* set address */
    if (err < 0) 
    {
        s_UartPrint("\n      USB device not accepting new address (error=%lX)\n", dev->status);
        s_UartPrint("NEW_step 6\n");
        return 1;
    }
    wait_ms(10);	/* Let the SET_ADDRESS settle */
    tmp = sizeof(dev->descriptor);
    err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
    if (err < tmp) 
    {
        if (err < 0)
        s_UartPrint("unable to get device descriptor (error=%d)\n",err);
        else
        s_UartPrint("USB device descriptor short read (expected %i, got %i)\n",tmp,err);
        s_UartPrint("NEW_step 8\n");
        return 1;
    }
    /* correct le values */
    dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB);
    dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor);
    dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct);
    dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice);
    USB_PRINTF("bLength %x\n", dev->descriptor.bLength);
    USB_PRINTF("bDescriptorType      %x\n", dev->descriptor.bDescriptorType);
    USB_PRINTF("bcdUSB      %x\n", dev->descriptor.bcdUSB);
    USB_PRINTF("bDeviceClass     %x\n", dev->descriptor.bDeviceClass);
    USB_PRINTF("bDeviceSubClass     %x\n", dev->descriptor.bDeviceSubClass);
    USB_PRINTF("bDeviceProtocol      %x\n", dev->descriptor.bDeviceProtocol);
    USB_PRINTF("bMaxPacketSize0      %x\n", dev->descriptor.bMaxPacketSize0);
    USB_PRINTF("idVendor      %x\n", dev->descriptor.idVendor);
    USB_PRINTF("idProduct      %x\n", dev->descriptor.idProduct);
    USB_PRINTF("bcdDevice      %x\n", dev->descriptor.bcdDevice);
    USB_PRINTF("iManufacturer      %x\n", dev->descriptor.iManufacturer);
    USB_PRINTF("iProduct      %x\n", dev->descriptor.iProduct);
    USB_PRINTF("iSerialNumber      %x\n", dev->descriptor.iSerialNumber);
    USB_PRINTF("bNumConfigurations      %x\n", dev->descriptor.bNumConfigurations);
    /* only support for one config for now */
    usb_get_configuration_no(dev,&tmpbuf[0],0);
    usb_parse_config(dev,&tmpbuf[0],0);
    usb_set_maxpacket(dev);
    /* we set the default configuration here */

	set_root_hub_configration();

    USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
    dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
    memset(dev->mf, 0, sizeof(dev->mf));
    memset(dev->prod, 0, sizeof(dev->prod));
    memset(dev->serial, 0, sizeof(dev->serial));
#if 0
    if (dev->descriptor.iManufacturer)
	    usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf));
    if (dev->descriptor.iProduct)
    	usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod));
    if (dev->descriptor.iSerialNumber)
	    usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial));
#endif
    USB_PRINTF("Manufacturer %s\n", dev->mf);
    USB_PRINTF("Product      %s\n", dev->prod);
    USB_PRINTF("SerialNumber %s\n", dev->serial);
    /* now prode if the device is a hub */
    usb_hub_probe(dev,0);
    return 0;
}

void gm_init_root_hub(void)
{
	gm_usb_new_root_hub();
}

/* build device Tree  */
void init_root_hub(void)
{
    int i;
    struct usb_device *dev;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
#if 0
    /* first make all devices unknown */
    for(i=0;i<USB_MAX_DEVICE;i++) 
    {        
        memset(&usb_dev[i],0,sizeof(struct usb_device));
        usb_dev[i].devnum=-1;
    }
    dev_index=0;
    /* device 0 is always present (root hub, so let it analyze) */
    //s_UartPrint("scan_step 1\n");
    dev=usb_alloc_new_device();
    s_UartPrint("scan_step 2\n");
	s_UartPrint("dev=%d",dev);
#endif
	gm_usb_new_root_hub();
    //usb_new_root_hub(dev);
    //s_UartPrint("scan_step 3\n");
    //s_UartPrint("%d USB Device(s) found\n",dev_index);
    /* insert "driver" if possible */
}

/* build device Tree  */
void usb_scan_devices(void)
{
    int i;
    struct usb_device *dev;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    /* first make all devices unknown */
#if 0
    for(i=0;i<USB_MAX_DEVICE;i++) 
    {        
        memset(&usb_dev[i],0,sizeof(struct usb_device));
        usb_dev[i].devnum=-1;
    }
#endif
    dev_index=1;
    /* device 0 is always present (root hub, so let it analyze) */
    //s_UartPrint("scan_step 1\n");
    dev=usb_alloc_new_device();
    s_UartPrint("scan_step 2\n");
	s_UartPrint("dev=%d",dev);
    usb_new_device(dev);
    //s_UartPrint("scan_step 3\n");
    //s_UartPrint("%d USB Device(s) found\n",dev_index);
    /* insert "driver" if possible */
}


/****************************************************************************
 * HUB "Driver"
 * Probes device for being a hub and configurate it
 */
#undef	USB_HUB_DEBUG
//#define   USB_HUB_DEBUG
#ifdef	USB_HUB_DEBUG
#define	USB_HUB_PRINTF	s_UartPrint
#else
void USB_HUB_PRINTF(char *fmt,...){}
#endif
static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;
int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
	    					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
					    	USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);
}


int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
						    USB_REQ_CLEAR_FEATURE,
							USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_set_port_feature(struct usb_device *dev, int port, int feature)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_get_hub_status(struct usb_device *dev, void *data)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
    data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}


int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
    data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}


static void usb_hub_power_on(struct usb_hub_device *hub)
{
    int i;
    struct usb_device *dev;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    dev=hub->pusb_dev;
    /* Enable power to the ports */
    USB_HUB_PRINTF("enabling power on all ports\n");
    for (i = 0; i < dev->maxchild; i++) 
    {
        usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
        USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status);
        wait_ms(hub->desc.bPwrOn2PwrGood * 2);
    }
}


void usb_hub_reset(void)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    usb_hub_index=0;
}


struct usb_hub_device *usb_hub_allocate(void)
{
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    if(usb_hub_index<USB_MAX_HUB) 
    {
        return &hub_dev[usb_hub_index++];
    }
    s_UartPrint("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB);
    return NULL;
}

int gm_root_hub_port_reset(int port)
{
    int tries;
    struct usb_port_status portsts;
    unsigned short portstatus, portchange;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    for(tries=0;tries<5;tries++) 
    {
		gm_hub_port_reset(port+1);
        wait_ms(200);

		gm_get_port_status(&portsts, port + 1);
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);

        if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
	        !(portstatus & USB_PORT_STAT_CONNECTION))
		{
    	    return -1;
		}

        if (portstatus & USB_PORT_STAT_ENABLE) 
        {
            break;
        }
        wait_ms(200);
    }
    if (tries==5) 
    {
        s_UartPrint("Cannot enable port %i after %i retries, disabling port.\n", port+1, 5);
        s_UartPrint("Maybe the USB cable is bad?\n");
        return -1;
    }

	gm_clear_port_c_reset(port+1);
    return 0;
}

#define MAX_TRIES 5
static int hub_port_reset(struct usb_device *dev, int port,
unsigned short *portstat)
{
    int tries;
    struct usb_port_status portsts;
    unsigned short portstatus, portchange;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
    USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
    for(tries=0;tries<MAX_TRIES;tries++) 
    {
		gm_hub_port_reset(port+1);
        //usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
        wait_ms(200);
		gm_get_port_status(&portsts, port + 1);
#if 0
        if (usb_get_port_status(dev, port + 1, &portsts)<0) 
        {
            USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status);
            return -1;
        }
#endif
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);
#if 0
        USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange,
        portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
        USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d  USB_PORT_STAT_ENABLE %d\n",
        (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
        (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,
        (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
#endif
        if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
        !(portstatus & USB_PORT_STAT_CONNECTION))
        return -1;
        if (portstatus & USB_PORT_STAT_ENABLE) 
        {
            break;
        }
        wait_ms(200);
    }
    if (tries==MAX_TRIES) 
    {
        USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES);
        USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
        return -1;
    }
    USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	gm_clear_port_c_reset(port+1);
    //usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
    *portstat = portstatus;
    return 0;
}
#if 0
struct usb_device_descriptor 
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short bcdUSB;
    unsigned char  bDeviceClass;
    unsigned char  bDeviceSubClass;
    unsigned char  bDeviceProtocol;
    unsigned char  bMaxPacketSize0;
    unsigned short idVendor;
    unsigned short idProduct;
    unsigned short bcdDevice;
    unsigned char  iManufacturer;
    unsigned char  iProduct;
    unsigned char  iSerialNumber;
    unsigned char  bNumConfigurations;
};
#endif

void print_device_desc(void *data)
{
	struct usb_device_descriptor *buffer = (struct usb_device_descriptor *)data;

	s_UartPrint("device desc:\n bDescriptorType 0x%x\n bcdUSB 0x%x\n bDeviceClass 0x%x\n bDeviceSubClass 0x%x\n bDeviceProtocol 0x%x\n bMaxPacketSize0 0x%x\n idVendor 0x%x\n idProduct 0x%x\n bcdDevice 0x%x\n iManufacturer 0x%x\n iProduct 0x%x\n iSerialNumber 0x%x\n \n",
			//buffer->bLength,//无法打印?
			buffer->bDescriptorType,
			buffer->bcdUSB,
			buffer->bDeviceClass,
			buffer->bDeviceSubClass,
			buffer->bDeviceProtocol,
			buffer->bMaxPacketSize0,
			buffer->idVendor,
			buffer->idProduct,
			buffer->bcdDevice,
			buffer->iManufacturer,
			buffer->iProduct,
			buffer->iSerialNumber
			//,buffer->bNumConfigurations
			);
}

#if 0
struct usb_config_descriptor
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned short wTotalLength;
    unsigned char  bNumInterfaces;
    unsigned char  bConfigurationValue;
    unsigned char  iConfiguration;
    unsigned char  bmAttributes;
    unsigned char  MaxPower;
    unsigned char  no_of_if;        /* number of interfaces */
    struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
};
#endif

void print_configuration_desc(void *data)
{
	struct usb_config_descriptor *buffer = (struct usb_config_descriptor*)data;
	s_UartPrint("configuration desc:\n bLength 0x%x\n bDescriptorType 0x%x\n wTotalLength 0x%x\n bNumInterfaces 0x%x\n bConfigurationValue 0x%x\n iConfiguration 0x%x\n bmAttributes 0x%x\n MaxPower 0x%x\n",
					buffer->bLength,
					buffer->bDescriptorType,
					buffer->wTotalLength,
					buffer->bNumInterfaces,
					buffer->bConfigurationValue,
					buffer->iConfiguration,
					buffer->bmAttributes,
					buffer->MaxPower);
}

#if 0
struct usb_interface_descriptor
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bInterfaceNumber;
    unsigned char  bAlternateSetting;
    unsigned char  bNumEndpoints;
    unsigned char  bInterfaceClass;
    unsigned char  bInterfaceSubClass;
    unsigned char  bInterfaceProtocol;
    unsigned char  iInterface;
    unsigned char  no_of_ep;
    unsigned char  act_altsetting;
    struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
};
#endif

void print_interface_desc(void *data)
{
	struct usb_interface_descriptor *buffer = (struct usb_interface_descriptor*)data;

	s_UartPrint("interface desc:\n bLength 0x%x\n bDescriptorType 0x%x\n bInterfaceNumber 0x%x\n bAlternateSetting 0x%x\n bNumEndpoints 0x%x\n bInterfaceClass 0x%x\n bInterfaceSubClass 0x%x\n bInterfaceProtocol 0x%x\n iInterface 0x%x\n",
			buffer->bLength,
			buffer->bDescriptorType,
			buffer->bInterfaceNumber,
			buffer->bAlternateSetting,
			buffer->bNumEndpoints,
			buffer->bInterfaceClass,
			buffer->bInterfaceSubClass,
			buffer->bInterfaceProtocol,
			buffer->iInterface);
}

#if 0
struct usb_endpoint_descriptor
{
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bEndpointAddress;
    unsigned char  bmAttributes;
    unsigned short wMaxPacketSize;
    unsigned char  bInterval;
    unsigned char  bRefresh;
    unsigned char  bSynchAddress;
};
#endif

void print_endpiont_desc(void *data)
{
	unsigned char *buffer = (unsigned char*)data;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

	s_UartPrint("endpoint desc:\n");
	s_UartPrint("bLength 0x%x\n", buffer[0]);
	s_UartPrint("bDescriptorType 0x%x\n", buffer[1]);
	s_UartPrint("bEndpointAddress 0x%x\n", buffer[2]);
	s_UartPrint("bmAttributes 0x%x\n", buffer[3]);
	//s_UartPrint("wMaxPacketSize 0x%x\n", *((unsigned short*)&buffer[4]));
	s_UartPrint("bInterval 0x%x\n", buffer[6]);
}

/* 找到一个匹配的描述符就返回...
 * @desc_type: 欲寻找的描述符类型.*/
void *find_desc(void *data, int be, unsigned char desc_type)
{
	unsigned char length = 0;
	unsigned char tmp_type = 0;
	unsigned char *buffer = data;

	void *desc = NULL;

	while(((int)buffer) < be)
	{
		length = buffer[0];
		tmp_type = buffer[1];

		if(tmp_type==desc_type){
			desc = buffer;
			break;
		}

		buffer += length;
	}

	return desc;
}

struct usb_hid_descriptor {
	unsigned char bLength;
	unsigned char bDescriptorType;
	unsigned short bcdHID;
	unsigned char bContryCode;
	unsigned char bNumDescriptor;
	unsigned char bSubDescriptor;
	unsigned short wDescriptorLength;
};

void print_hid_desc(void *data)
{
	struct usb_hid_descriptor *buffer = data;

	s_UartPrint("hid desc:\n");
	s_UartPrint(" bDescriptorType 0x%x\n", buffer->bDescriptorType);
	s_UartPrint(" bcdHID 0x%x\n", buffer->bcdHID);
	s_UartPrint(" bContryCode 0x%x\n", buffer->bContryCode);
	s_UartPrint(" bNumDescriptor 0x%x\n", buffer->bNumDescriptor);
	s_UartPrint(" bSubDescriptor 0x%x\n", buffer->bSubDescriptor);
	s_UartPrint(" wDescriptorLength 0x%x\n", buffer->wDescriptorLength);
}

void mouse_probe(unsigned char *data, int data_size)
{
	struct usb_hid_descriptor *hid_desc = NULL;
	unsigned char buffer[120] = {0};

	hid_desc = find_desc(data, data_size, 0x21);

	print_hid_desc(hid_desc);

	gm_set_HID_idle();

	gm_get_hid_report(buffer, sizeof(buffer));

	while(1)
		gm_get_IN_data(buffer, 8);
}

void usb_clear_ep_halt(unsigned char bEndpointAddress)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
	/* ep */
    setup_packet.requesttype = 0x02;
	/* clear feature */
    setup_packet.request = 0x1;
	/* clear ep halt status */
    setup_packet.value = 0;

    setup_packet.index = bEndpointAddress;
	/* 无 数据传输过程 */
    setup_packet.length = 0;

	gm_ep_set(2,0,0,0,0,0,0x8);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

void bot_udisk_reset(int interface_num)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
	/* class, interface, host to device */
    setup_packet.requesttype = 0x21;
	/* Mass storage reset. */
    setup_packet.request = 0xFF;
    setup_packet.value = 0;
    setup_packet.index = interface_num;
	/* 无 数据传输过程 */
    setup_packet.length = 0;

	gm_ep_set(2,0,0,0,0,0,0x8);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

void usb_get_disk_max_lun(void *buffer, int interface_num)
{
	U32 td_info = 0;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

    /* set setup command */
	/* class, interface, device to host */
    setup_packet.requesttype = 0xA1;
	/* get max lun */
    setup_packet.request = 0xFE;
    setup_packet.value = 0;
    setup_packet.index = interface_num;
	/* 无 数据传输过程 */
    setup_packet.length = 1;

	/* 由于传输长度为1, ed的包大小为8也无所谓... */
	gm_ep_set(2,0,0,0,0,0,0x8);

	td_info = create_td_info(1, 0x00, 0x00, 0x2, 0x0, 0xf);
	gm_set_td(0, 0, td_info, (void *)&setup_packet, 8);

	td_info = create_td_info(1, 2, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(1, 0, td_info, buffer, setup_packet.length);

	td_info = create_td_info(1, 1, 0x00, 0x3, 0x0, 0xf);
	gm_set_td(2, 1, td_info, 0, 0);

	gm_start_td();

	gm_wait_hc_interrput();
}

/* 计算接下来的TD需要的DATAx. */
void cal_next_toggle(int data_size, int mps, U32 *toggle)
{
	int td_num = 0;

	/* 计算需要多少个TD来传输数据 */
	td_num = data_size/mps;
	td_num += (data_size%mps)?1:0;

	if(td_num%2) {
		/* 对toogle取反. */
		*toggle = (*toggle)?0:1;
	}
}

void usb_bulk_trans(void *data, int data_size, int mps, struct usb_endpoint_descriptor *ed)
{
	U32 td_info = 0;
	int direction = -1;
	U32 *tmp_toggle = NULL;

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

	/* 2: IN; 1:OUT; */
	direction = ed->bEndpointAddress&0x80?2:1;
	gm_bulk_ep_set(2,ed->bEndpointAddress&0xF,0,0,0,0,mps);

	tmp_toggle = (direction==2)?(&ed_in_toogle):(&ed_out_toogle);

	/* 即使传输巨量数据, 也无需我们创建多个TD. host会根据buffer的起始地址和尾地址,
	 * 自动发送对应数目的TD.*/
	td_info = create_td_info(1, direction, 0x00, (0x1<<1)|((*tmp_toggle)&0x1), 0x0, 0xf);
	gm_set_td(0, 1, td_info, data, data_size);

	gm_start_bulk_td();

	gm_wait_hc_interrput();

	cal_next_toggle(data_size, mps, tmp_toggle);
}

/* 大端,小端的相互转换 */
U32 BE_LE_change32(U32 data)
{
	return (data&0xFF)<<24 | (data&0xFF00)<<8 | (data&0xFF0000)>>8 | (data&0xFF000000)>>24;
}

U16 BE_LE_change16(U16 data)
{
	return (data&0xFF)<<8 | (data&0xFF00)>>8;
}

U8 usb_disk_read_data(int mps, struct usb_endpoint_descriptor *ed_out, struct usb_endpoint_descriptor *ed_in,
								U32 block_addr, U16 block_count, U32 block_size, U8 *buffer)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;

	U32 *pblock_addr_tmp = NULL;
	U16 *pblock_count_tmp = NULL;

	s_UartPrint("%s, %d.\n", __func__, __LINE__);

	memset(cbw.CBWCDB, 0, CBWCDBLENGTH);

	cbw.dCBWSignature = CBWSIGNATURE;
	cbw.dCBWTag = cbwtag++;
	cbw.dCBWDataTransferLength = block_count*block_size;
	cbw.bCBWFlags = 0x80; /* 请求数据输入 */
	cbw.bCBWLUN = 0; /* 目标lun的编号. 一般U盘只有一个lun,即其编号为0 */
	cbw.bCBWCBLength = 12; /* 命令长度. */

	/* 命令码 */
	cbw.CBWCDB[0] = 0x28;
	cbw.CBWCDB[1] = cbw.bCBWLUN<<5;


	cbw.CBWCDB[2] = (block_addr>>24)&0xFF;
	cbw.CBWCDB[3] = (block_addr>>16)&0xFF;
	cbw.CBWCDB[4] = (block_addr>>8)&0xFF;
	cbw.CBWCDB[5] = (block_addr>>0)&0xFF;


	cbw.CBWCDB[7] = (block_count>>8)&0xFF;
	cbw.CBWCDB[8] = (block_count>>0)&0xFF;

	/* 命令阶段 */
	/* sizeof(cbw)值是32, 与实际31不符. 导致device解析命令失败.... */
	usb_bulk_trans((void *)&cbw, /*sizeof(cbw)*/31, mps, ed_out);
	/* 数据阶段 */
	usb_bulk_trans((void *)buffer, cbw.dCBWDataTransferLength, mps, ed_in);
	/* 状态阶段 */
	usb_bulk_trans((void *)&csw, 13, mps, ed_in);

	return csw.bCSWStatus;
}

U8 usb_disk_read_capacity(int mps, struct usb_endpoint_descriptor *ed_out, struct usb_endpoint_descriptor *ed_in, U32 *addr, U32 *blk_size)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;

	unsigned char buffer[36] = {0};
	U32 *data = NULL;
	U32 size = 0;
	U32 max_addr, block_size;

	memset(cbw.CBWCDB, 0, CBWCDBLENGTH);

	cbw.dCBWSignature = CBWSIGNATURE;
	cbw.dCBWTag = cbwtag++;
	cbw.dCBWDataTransferLength = 8;
	cbw.bCBWFlags = 0x80; /* 请求数据输入 */
	cbw.bCBWLUN = 0; /* 目标lun的编号. 一般U盘只有一个lun,即其编号为0 */
	cbw.bCBWCBLength = 12; /* 命令长度. */

	/* 命令码 */
	cbw.CBWCDB[0] = 0x25;

	/* 命令阶段 */
	/* sizeof(cbw)值是32, 与实际31不符. 导致device解析命令失败.... */
	usb_bulk_trans((void *)&cbw, /*sizeof(cbw)*/31, mps, ed_out);
	/* 数据阶段 */
	usb_bulk_trans((void *)buffer, sizeof(buffer), mps, ed_in);
	/* 状态阶段 */
	usb_bulk_trans((void *)&csw, 13, mps, ed_in);

	data = (U32 *)buffer;
	s_UartPrint("data[0] 0x%x.\n", data[0]);
	s_UartPrint("data[1] 0x%x.\n", data[1]);

	max_addr = BE_LE_change32(data[0]);
	block_size = BE_LE_change32(data[1]);

	s_UartPrint("block_size 0x%x.\n", block_size);

	size = (max_addr+1)>>10;
	size = (size*block_size)>>10;

	*addr = max_addr;
	*blk_size = block_size;

	s_UartPrint("%s: udisk capacity: %d MB.\n", __func__, size);

	return csw.bCSWStatus;
}

U8 usb_disk_inquiry(int mps, struct usb_endpoint_descriptor *ed_out, struct usb_endpoint_descriptor *ed_in)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;

	unsigned char buffer[36] = {0};

	s_UartPrint("%s, %d.\n", __func__, __LINE__);

	memset(cbw.CBWCDB, 0, CBWCDBLENGTH);

	cbw.dCBWSignature = CBWSIGNATURE;
	cbw.dCBWTag = cbwtag++;
	cbw.dCBWDataTransferLength = 36;
	cbw.bCBWFlags = 0x80; /* 请求数据输入 */
	cbw.bCBWLUN = 0; /* 目标lun的编号. 一般U盘只有一个lun,即其编号为0 */
	cbw.bCBWCBLength = 12; /* 命令长度. */

	/* 命令码 */
	cbw.CBWCDB[0] = 0x12;
	cbw.CBWCDB[1] = cbw.bCBWLUN<<5;
	cbw.CBWCDB[4] = cbw.dCBWDataTransferLength;

	s_UartPrint("cbw size %d.\n", sizeof(cbw));

	/* 命令阶段 */
	/* sizeof(cbw)值是32, 与实际31不符. 导致device解析命令失败.... */
	usb_bulk_trans((void *)&cbw, /*sizeof(cbw)*/31, mps, ed_out);
	/* 数据阶段 */
	usb_bulk_trans((void *)buffer, sizeof(buffer), mps, ed_in);
	/* 状态阶段, toggle必须为1, 否则报cc=3(toggle不符) */
	usb_bulk_trans((void *)&csw, 13, mps, ed_in);

	return csw.bCSWStatus;
}

U8 usb_disk_test_unit_ready(int mps,
				struct usb_endpoint_descriptor *ed_out, struct usb_endpoint_descriptor *ed_in)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;

	memset(cbw.CBWCDB, 0, CBWCDBLENGTH);

	cbw.dCBWSignature = CBWSIGNATURE;
	cbw.dCBWTag = cbwtag++;
	cbw.dCBWDataTransferLength = 0;
	cbw.bCBWFlags = 0x80; /* 请求数据输入 */
	cbw.bCBWLUN = 0; /* 目标lun的编号. 一般U盘只有一个lun,即其编号为0 */
	cbw.bCBWCBLength = 12; /* 命令长度. */

	/* 命令码 */
	cbw.CBWCDB[0] = 0x00;
	cbw.CBWCDB[1] = cbw.bCBWLUN<<5;

	/* 命令阶段 */
	/* sizeof(cbw)值是32, 与实际31不符. 导致device解析命令失败.... */
	usb_bulk_trans((void *)&cbw, /*sizeof(cbw)*/31, mps, ed_out);
	/* 数据阶段 */
	//usb_bulk_trans((void *)buffer, sizeof(buffer), mps, ed_in, 0);
	/* 状态阶段 */
	usb_bulk_trans((void *)&csw, 13, mps, ed_in);

	return csw.bCSWStatus;
}

void udisk_probe(unsigned char *buffer, int data_size, struct usb_endpoint_descriptor **ep_array, int mps)
{
	struct usb_config_descriptor *config_desc = NULL;
	struct usb_interface_descriptor *interface_desc = NULL;

	struct usb_endpoint_descriptor *ep_desc_IN = NULL;
	struct usb_endpoint_descriptor *ep_desc_OUT = NULL;

	int max_lun = 0;
	U8 status;
	U32 max_addr = 0;
	U32 block_size = 0;

	U8 disk_buffer[1024] = {0};

	config_desc = (struct usb_config_descriptor*)buffer;
	interface_desc = (struct usb_interface_descriptor*)(buffer + config_desc->bLength);

	/* 我知道这个U盘只有两个端点... */
	/* 取端点方向 */
	if(ep_array[0]->bEndpointAddress & 0x80) {
		ep_desc_IN = ep_array[0];
	} else {
		ep_desc_OUT = ep_array[0];
	}

	if(ep_array[1]->bEndpointAddress & 0x80) {
		ep_desc_IN = ep_array[1];
	} else {
		ep_desc_OUT = ep_array[1];
	}

	switch(interface_desc->bInterfaceProtocol) {
		case US_PR_BULK:
			s_UartPrint("%s: bot udisk.\n", __func__);
			break;
		default:
			s_UartPrint("%s: just support BOT.\n", __func__);
			goto out;
	}

	/* 可以不执行;
	 *
	 * max_lun: 如果设备有4个lun, lun从0~3计数. 此时max_lun=3;
	 * 			如果设备有1个lun, 此时max_lun=0.*/
	usb_get_disk_max_lun((void *)&max_lun, 0);
	s_UartPrint("%s: max lun %d.\n", __func__, max_lun);

	/* reset 接口0上的udisk. */
	bot_udisk_reset(0);
	wait_ms(150);
	/* reset ep, 清除其halt的状态. */
	usb_clear_ep_halt(ep_desc_IN->bEndpointAddress);
	wait_ms(150);
	usb_clear_ep_halt(ep_desc_OUT->bEndpointAddress);
	wait_ms(150);

	/* DATA0->DATA0->DATA1 */
	status = usb_disk_inquiry(mps, ep_desc_OUT, ep_desc_IN);
	if(status) {
		s_UartPrint("%s: usb_disk_inquiry error.\n", __func__);
		goto out;
	}
	/* DATA1->DATA0 ? */
	status = usb_disk_test_unit_ready(mps, ep_desc_OUT, ep_desc_IN);
	if(status) {
		s_UartPrint("%s: usb_disk_test_unit_ready error.\n", __func__);
		goto out;
	}

	usb_disk_read_capacity(mps, ep_desc_OUT, ep_desc_IN, &max_addr, &block_size);

	usb_disk_read_data(mps, ep_desc_OUT, ep_desc_IN, 0, 1, block_size, disk_buffer);
out:
	return ;
}

/* 此函数的使用情景仅为鼠标设备. 一个配置,一个接口,一个端点. */
void gm_usb_hub_port_connect_change(int port)
{
    struct usb_device usb;
	unsigned char buffer[100] = {0};
	struct usb_device_descriptor *device_desc = NULL;
	struct usb_config_descriptor *config_desc = NULL;
	struct usb_interface_descriptor *interface_desc = NULL;
	struct usb_endpoint_descriptor *ep_desc[8];
	unsigned char *tmp_buffer = NULL;
	int i = 0;
	int MPS = 8; /* 端点的最大包大小 */

	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

	gm_clear_port_c_connect(port+1);

    wait_ms(200);
    /* Reset the port */
	gm_root_hub_port_reset(port);

    wait_ms(200);
	MPS = gm_get_device_descriptor(buffer, 8, 8, 0);

	/* 满速传输最大为64 */
	if(MPS > 64) {
		MPS = 64;
	}

	gm_set_device_address();
	wait_ms(200);

	device_desc = (struct usb_device_descriptor *)buffer;
	gm_get_device_descriptor(buffer, device_desc->bLength, MPS, 2);
	print_device_desc(buffer);

	gm_get_device_configuration(buffer, 8, MPS);
	config_desc = (struct usb_config_descriptor*)buffer;

	gm_get_device_configuration(buffer, config_desc->wTotalLength, MPS);
	print_configuration_desc(buffer);

	interface_desc = (struct usb_interface_descriptor*)(buffer + config_desc->bLength);
	print_interface_desc(interface_desc);

	tmp_buffer = buffer;
	for(i=0; i<interface_desc->bNumEndpoints; i++){
		tmp_buffer = (find_desc(tmp_buffer, (int)(buffer+config_desc->wTotalLength-1), 5));

		ep_desc[i] = (struct usb_endpoint_descriptor*)tmp_buffer;

		/* 地址递增, 否则find_desc函数又会找到此ep... */
		tmp_buffer += ep_desc[i]->bLength;

		s_UartPrint("%s: ep_desc[%d] addr 0x%x.\n", __func__, i, ep_desc);

		print_endpiont_desc(ep_desc[i]);
	}

	gm_set_configuration(config_desc->bConfigurationValue);

	ed_in_toogle = 0;
	ed_out_toogle = 0;

	udisk_probe(buffer, config_desc->wTotalLength, ep_desc, MPS);
	//mouse_probe(buffer, config_desc->wTotalLength);
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
	while(1);
}

void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
    struct usb_device usb;
    struct usb_port_status portsts;
    unsigned short portstatus, portchange;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
#if 0
    /* Check status */
	gm_get_port_status(&portsts, port + 1);
    if (usb_get_port_status(dev, port + 1, &portsts)<0) 
    {
        USB_HUB_PRINTF("get_port_status failed\n");
        return;
    }
    portstatus = swap_16(portsts.wPortStatus);
    portchange = swap_16(portsts.wPortChange);
    USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,
    portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
    /* Clear the connection change status */
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);
#endif
	gm_clear_port_c_connect(port+1);
#if 0
    //usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
    /* Disconnect any existing devices under this port */
    if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
    (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) 
    {
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
        USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
        /* Return now if nothing is connected */
        if (!(portstatus & USB_PORT_STAT_CONNECTION))
        return;
    }
#endif
    wait_ms(200);
    /* Reset the port */

	gm_root_hub_port_reset(port);
#if 0
    if (hub_port_reset(dev, port, &portstatus) < 0) 
    {
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
        USB_HUB_PRINTF("cannot reset port %i!?\n", port + 1);
        return;
    }
#endif
    wait_ms(200);
#if 0
    /* Allocate a new device struct for it */
    usb=usb_alloc_new_device();
    usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
    dev->children[port] = usb;
    usb->parent=dev;
#endif
    /* Run it through the hoops (find a driver, etc) */
	//gm_usb_new_device(&usb);
#if 0
    if (usb_new_device(usb)) 
    {
		s_UartPrint("in %s, %d.\n",__func__, __LINE__);
        /* Woops, disable the port */
        USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
        usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
    }
#endif
}

int gm_usb_hub_configure(void)
{
    unsigned char buffer[USB_BUFSIZ];
    struct usb_hub_descriptor *descriptor;
	int maxchild = 0;
	int i = 0;
	struct usb_port_status portsts;
	unsigned short portstatus, portchange;

	gm_get_hub_descriptor(buffer, 4);
    descriptor = (struct usb_hub_descriptor *)buffer;
	gm_get_hub_descriptor(buffer, descriptor->bLength);
    maxchild = descriptor->bNbrPorts;

	gm_set_rh_power_on(1);
	gm_set_rh_power_on(2);
    for (i = 0; i < maxchild; i++) 
    {
		gm_get_port_status(&portsts, i+1);

        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);

		/* 判断HcRhPortStatus的CCS位, 是否有设备连接了? */
        if (portchange & USB_PORT_STAT_C_CONNECTION) 
        {
            USB_HUB_PRINTF("port %d connection change\n", i + 1);
			gm_usb_hub_port_connect_change(i);
        }
	}
}

int usb_hub_configure(struct usb_device *dev)
{
    unsigned char buffer[USB_BUFSIZ], *bitmap;
    struct usb_hub_descriptor *descriptor;
    struct usb_hub_status *hubsts;
    int i;
    struct usb_hub_device *hub;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

#if 0
    /* "allocate" Hub device */
    hub=usb_hub_allocate();
    if(hub==NULL)
    	return -1;
    hub->pusb_dev=dev;
#endif
    /* Get the the hub descriptor */
	gm_get_hub_descriptor(buffer, 4);
#if 0
    if (usb_get_hub_descriptor(dev, buffer, 4) < 0) {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor %lX\n",dev->status);
        return -1;
    }
#endif
    descriptor = (struct usb_hub_descriptor *)buffer;
#if 0
    /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
    i = descriptor->bLength;
    if (i > USB_BUFSIZ) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor - too long: %d\n",
        descriptor->bLength);
        return -1;
    }
#endif
	gm_get_hub_descriptor(buffer, descriptor->bLength);
#if 0
    if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status);
        return -1;
    }
#endif
#if 0
    memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength);
    /* adjust 16bit values */
    hub->desc.wHubCharacteristics=swap_16(descriptor->wHubCharacteristics);
    /* set the bitmap */
    bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0];
    memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */
    bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0];
    memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */
    for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) 
    {
        hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i];
    }
    for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) 
    {
        hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i];
    }
#endif
    dev->maxchild = descriptor->bNbrPorts;
#if 0
    USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
    switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) 
    {
    case 0x00:
        USB_HUB_PRINTF("ganged power switching\n");
        break;
    case 0x01:
        USB_HUB_PRINTF("individual port power switching\n");
        break;
    case 0x02:
    case 0x03:
        USB_HUB_PRINTF("unknown reserved power switching mode\n");
        break;
    }
    if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
    USB_HUB_PRINTF("part of a compound device\n");
    else
    USB_HUB_PRINTF("standalone hub\n");
    switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) 
    {
    case 0x00:
        USB_HUB_PRINTF("global over-current protection\n");
        break;
    case 0x08:
        USB_HUB_PRINTF("individual port over-current protection\n");
        break;
    case 0x10:
    case 0x18:
        USB_HUB_PRINTF("no over-current protection\n");
        break;
    }
    USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2);
    USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent);
    for (i = 0; i < dev->maxchild; i++){
	    USB_HUB_PRINTF("port %d is%s removable\n", i + 1,
    		hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : "");
	}
    if (sizeof(struct usb_hub_status) > USB_BUFSIZ) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get Status - too long: %d\n",
        descriptor->bLength);
        return -1;
    }
	gm_get_rh_status(buffer);
    if (usb_get_hub_status(dev, buffer) < 0) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status);
        return -1;
    }
    hubsts = (struct usb_hub_status *)buffer;
#endif

	gm_set_rh_power_on(1);
	gm_set_rh_power_on(2);
    //usb_hub_power_on(hub);
    for (i = 0; i < dev->maxchild; i++) 
    {
        struct usb_port_status portsts;
        unsigned short portstatus, portchange;

		gm_get_port_status(&portsts, i+1);
#if 0
        if (usb_get_port_status(dev, i + 1, &portsts) < 0) 
        {
            USB_HUB_PRINTF("get_port_status failed\n");
            continue;
        }
#endif
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);
        USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange);
        if (portchange & USB_PORT_STAT_C_CONNECTION) 
        {
            USB_HUB_PRINTF("port %d connection change\n", i + 1);
			gm_usb_hub_port_connect_change(i);
            //usb_hub_port_connect_change(dev, i);
        }
#if 0
		/* GM: fix me */
        if (portchange & USB_PORT_STAT_C_ENABLE) 
        {
            USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
            /* EM interference sometimes causes bad shielded USB devices to
            			 * be shutdown by the hub, this hack enables them again.
            			 * Works at least with mouse driver */
            if (!(portstatus & USB_PORT_STAT_ENABLE) &&
            (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) 
            {
                USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n",
                i + 1);
                usb_hub_port_connect_change(dev, i);
            }
        }
        if (portstatus & USB_PORT_STAT_SUSPEND) 
        {
            USB_HUB_PRINTF("port %d suspend change\n", i + 1);
            usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);
        }
        if (portchange & USB_PORT_STAT_C_OVERCURRENT) 
        {
            USB_HUB_PRINTF("port %d over-current change\n", i + 1);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
            usb_hub_power_on(hub);
        }
        if (portchange & USB_PORT_STAT_C_RESET) 
        {
            USB_HUB_PRINTF("port %d reset change\n", i + 1);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
        }
#endif
    } 
    /* end for i all ports */
    return 0;
}


int usb_hub_probe(struct usb_device *dev, int ifnum)
{
    struct usb_interface_descriptor *iface;
    struct usb_endpoint_descriptor *ep;
    int ret;
	s_UartPrint("in %s, %d.\n",__func__, __LINE__);

#if 0
    iface = &dev->config.if_desc[ifnum];
    /* Is it a hub? */
    if (iface->bInterfaceClass != USB_CLASS_HUB)
	    return 0;
    /* Some hubs have a subclass of 1, which AFAICT according to the */
    /*  specs is not defined, but it works */
    if ((iface->bInterfaceSubClass != 0) &&(iface->bInterfaceSubClass != 1))
	    return 0;
    /* Multiple endpoints? What kind of mutant ninja-hub is this? */
    if (iface->bNumEndpoints != 1)
    	return 0;
    ep = &iface->ep_desc[0];
    /* Output endpoint? Curiousier and curiousier.. */
    if (!(ep->bEndpointAddress & USB_DIR_IN))
	    return 0;
    /* If it's not an interrupt endpoint, we'd better punt! */
    if ((ep->bmAttributes & 3) != 3)
    	return 0;
#endif
    /* We found a hub */
    USB_HUB_PRINTF("USB hub found\n");
	gm_usb_hub_configure();
    //ret=usb_hub_configure(dev);

    return ret;
}


//#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */
/* EOF */
